package com.my.zl.console.common.aop;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.zip.DataFormatException;

import javax.servlet.http.HttpServletRequest;

import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.NoHandlerFoundException;

import com.my.zl.common.dto.ResDTO;
import com.my.zl.common.enums.resp.GlobalEnum;
import com.my.zl.common.exception.BizException;
import com.my.zl.common.utils.ReturnUtil;
 
/**
 * 全局异常捕获处理，返回json
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 按http状态
     * 捕捉404异常
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResDTO<T> handle404(NoHandlerFoundException e) {
        LOGGER.error("路径不存在:{}，{}",e.getMessage(),e);
        return ReturnUtil.returnDATA(GlobalEnum.NOT_FOUND);
    }
    
    /**
     * http请求的方法不正确
     */
    @ResponseBody
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResDTO<T> httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException e) {
        LOGGER.error("http请求方法不正确:{}，{}",e.getMessage(),e);
        return ReturnUtil.returnDATA(GlobalEnum.RequestMethodNotAllowed);
    }
 
    /**
     * 请求参数不全
     */
    @ResponseBody
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResDTO<T> missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException e) {
        LOGGER.error("请求参数不全:{}，{}",e.getMessage(),e);
        return ReturnUtil.returnDATA(GlobalEnum.MissingServletRequestParameter);
    }
 
    /**
     * 请求参数类型不正确
     */
    @ResponseBody
    @ExceptionHandler(TypeMismatchException.class)
    public ResDTO<T> typeMismatchExceptionHandler(TypeMismatchException e) {
        LOGGER.error("请求参数类型不正确:{}，{}",e.getMessage(),e);
        return ReturnUtil.returnDATA(GlobalEnum.TypeMismatchException);
    }
 
    /**
     * 数据格式不正确
     */
    @ResponseBody
    @ExceptionHandler(DataFormatException.class)
    public ResDTO<T> dataFormatExceptionHandler(DataFormatException e) {
        LOGGER.error("数据格式不正确:{}，{}",e.getMessage(),e);
        return ReturnUtil.returnDATA(GlobalEnum.DataFormatException);
    }
 
    /**
     * 非法输入
     */
    @ResponseBody
    @ExceptionHandler(IllegalArgumentException.class)
    public ResDTO<T> illegalArgumentExceptionHandler(IllegalArgumentException e) {
        LOGGER.error("非法输入:{}，{}",e.getMessage(),e);
        return ReturnUtil.returnDATA(GlobalEnum.IllegalArgumentException);
    }
 
    @ResponseBody
    @ExceptionHandler(BizException.class)
    public ResDTO<T> bizExceptionHandler(BizException e) {
        LOGGER.error("业务异常:{}，{}",e.getMessage(),e);
        return ReturnUtil.returnDATA(e.getErrorCode(),e.getErrorMessage());
    }
    
    @ExceptionHandler  //处理其他异常
    @ResponseBody
    public ResDTO<T> allExceptionHandler(Exception e){
        LOGGER.error("Exception异常:{}", e);
        return ReturnUtil.errorDATA(null);
//      LOGGER.error("Exception异常:", getErrorMessage(e)); //会记录出错的代码行等具体信息
//        int count = 0; //只打印15行的错误堆栈
//        for (StackTraceElement stackTraceElement : e.getStackTrace()) {
//            LOGGER.error(stackTraceElement.toString());
//            if(count++ > 13) break;
//        }
       
    }
 
    
    /**
     * 获取异常信息
     *
     * @param e 异常
     */
    private static String getErrorMessage(Exception e) {
        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw = new PrintWriter(sw);
            // 将出错的栈信息输出到printWriter中
            e.printStackTrace(pw);
            pw.flush();
            sw.flush();
        } finally {
            if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    LOGGER.info(e1.getMessage());
                }
            }
            if (pw != null) {
                pw.close();
            }
        }
        return sw.toString();
    }
    
    /**
     * 获取状态码
     * @param request
     * @return
     */
    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }
}